/**
 * Moondance UML modeling tool
 * 
 * This program is free software; you can redistribute it and
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 3
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package ro.pub.cs.se.moondance.editpart;

import java.beans.PropertyChangeEvent;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.requests.DirectEditRequest;
import org.eclipse.gef.tools.DirectEditManager;
import org.eclipse.jface.viewers.TextCellEditor;

import ro.pub.cs.se.moondance.directedit.AttributeNameTypeCellEditorValidator;
import ro.pub.cs.se.moondance.directedit.ExtendedDirectEditManager;
import ro.pub.cs.se.moondance.directedit.LabelCellEditorLocator;
import ro.pub.cs.se.moondance.directedit.ValidationMessageHandler;
import ro.pub.cs.se.moondance.editor.ValidationEnabledGraphicalViewer;
import ro.pub.cs.se.moondance.editor.figures.EditableLabel;
import ro.pub.cs.se.moondance.editpolicy.AttributeDirectEditPolicy;
import ro.pub.cs.se.moondance.editpolicy.AttributeEditPolicy;
import ro.pub.cs.se.moondance.model.ClassVariable;

/**
 * Represents an editable Attribute object in the model
 */
public class AttributeEditPart extends UMLEntityEditPart {

	protected DirectEditManager manager;

	/**
	 * Creats EditPolicies for the attribute label
	 */
	protected void createEditPolicies() {
		installEditPolicy(EditPolicy.COMPONENT_ROLE, new AttributeEditPolicy());
		installEditPolicy(EditPolicy.DIRECT_EDIT_ROLE,
				new AttributeDirectEditPolicy());
		installEditPolicy(EditPolicy.LAYOUT_ROLE, null);
	}

	public void performRequest(Request request) {
		if (request.getType() == RequestConstants.REQ_DIRECT_EDIT) {
			if (request instanceof DirectEditRequest
					&& !directEditHitTest(((DirectEditRequest) request)
							.getLocation().getCopy()))
				return;
			performDirectEdit();
		}
	}

	private boolean directEditHitTest(Point requestLoc) {
		IFigure figure = getFigure();
		figure.translateToRelative(requestLoc);
		if (figure.containsPoint(requestLoc))
			return true;
		return false;
	}

	protected void performDirectEdit() {
		if (manager == null) {
			ValidationEnabledGraphicalViewer viewer = (ValidationEnabledGraphicalViewer) getViewer();
			ValidationMessageHandler handler = viewer.getValidationHandler();

			Label l = (Label) getFigure();
			AttributeNameTypeCellEditorValidator attributeNameTypeCellEditorValidator = new AttributeNameTypeCellEditorValidator(
					handler);

			manager = new ExtendedDirectEditManager(this, TextCellEditor.class,
					new LabelCellEditorLocator(l), l,
					attributeNameTypeCellEditorValidator);
		}
		manager.show();
	}

	/**
	 * Sets the width of the line when selected
	 */
	public void setSelected(int value) {
		super.setSelected(value);
		EditableLabel attributeLabel = (EditableLabel) getFigure();
		if (value != EditPart.SELECTED_NONE)
			attributeLabel.setSelected(true);
		else
			attributeLabel.setSelected(false);
		attributeLabel.repaint();
	}

	/**
	 * @param Handles
	 *            name change during direct edit
	 */
	public void handleNameChange(String textValue) {
		EditableLabel label = (EditableLabel) getFigure();
		label.setVisible(false);
		setSelected(EditPart.SELECTED_NONE);
		label.revalidate();
		refreshVisuals();
	}

	/**
	 * Handles when successfully applying direct edit
	 */
	protected void commitNameChange(PropertyChangeEvent evt) {
		EditableLabel label = (EditableLabel) getFigure();
		label.setText(getAttribute().getLabelText());
		setSelected(EditPart.SELECTED_PRIMARY);
		label.revalidate();
		refreshVisuals();
	}

	/**
	 * Reverts state back to prior edit state
	 */
	public void revertNameChange(String oldValue) {
		EditableLabel label = (EditableLabel) getFigure();
		label.setVisible(true);
		setSelected(EditPart.SELECTED_PRIMARY);
		label.revalidate();
		refreshVisuals();
	}

	/**
	 * We don't need to explicitly handle refresh visuals because the times when
	 * this needs to be done it is handled by the class e.g. handleNameChange()
	 */
	protected void refreshVisuals() {
		ClassVariable attribute = (ClassVariable) getModel();
		EditableLabel attributeLabel = (EditableLabel) getFigure();
		attributeLabel.setText(attribute.getLabelText());
	}

	private ClassVariable getAttribute() {
		return (ClassVariable) getModel();
	}

}